home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / programm.ing / winlib.lzh / WINLIB / FORMKBD.C < prev    next >
Encoding:
C/C++ Source or Header  |  1994-07-07  |  11.0 KB  |  545 lines

  1. /********************************************************************
  2.  *                                                                    *
  3.  *    WinLIB PRO Revision II: Custom text editor                        *
  4.  *                                                                    *
  5.  *    Copyright (c) 1994, Bitgate Software                            *
  6.  *                                                                    *
  7.  ********************************************************************/
  8.  
  9. #include <string.h>
  10. #include <stdio.h>
  11. #include <ctype.h>
  12.  
  13. #include "winlib.h"        /* WinLIB header file */
  14. #include "nkcc.h"        /* Normalized Keycodes header file */
  15.  
  16. #ifdef __TURBOC__
  17. #pragma warn -pia
  18. #endif
  19.  
  20. #ifndef __FORMKEYBOARD__
  21. #define __FORMKEYBOARD__
  22. #endif
  23.  
  24. /*
  25.  *  Turn the editing cursor off
  26.  */
  27. GLOBAL void edit_off(WINDOW *win)
  28. {
  29.     objc_edit(win->tree, win->edobject, 0, &win->edpos, ED_END);
  30. }
  31.  
  32.  
  33. /*
  34.  *  Turn on the editing cursor
  35.  */
  36. GLOBAL void edit_on(WINDOW *win)
  37. {
  38.     objc_edit(win->tree, win->edobject, 0, &win->edpos, ED_INIT);
  39. }
  40.  
  41.  
  42. /*
  43.  *  Reposition the cursor to an index
  44.  *  (It took a bit of thinking it out, but it worked in the end!)
  45.  *
  46.  *  where = offset into string to put cursor on
  47.  */
  48. GLOBAL void edit_pos(WINDOW *win, int where)
  49. {
  50.     register char c, *t = win->tree[win->edobject].ob_spec.tedinfo->te_ptext;
  51.  
  52.     if (where!=win->edpos) {
  53.         t += where;
  54.  
  55.         edit_off(win);
  56.         c = *t;
  57.         *t = 0;
  58.         edit_on(win);
  59.         *t = c;
  60.     }
  61. }
  62.  
  63. /*
  64.  *    Function to reposition cursor inside an object
  65.  *
  66.  *    This code segment by Jan Starzynski
  67.  *    Modifications by Ken Hollis
  68.  *
  69.  *    obj = Address of the root object (dialog box)
  70.  *    No  = editable object which was clicked on
  71.  *    mx  = X coordinate of mouse at time of click (from event info)
  72.  *
  73.  *    Returns
  74.  */
  75. GLOBAL int find_position(OBJECT *obj, int No, int mx)
  76. {
  77.     int te_x= 0;    /* Absolute coordinate of text */
  78.     int    P_text = 0;    /* Position in text */
  79.     int    P_mask = 0;    /* Position in mask */
  80.     int    size;        /* Text font size */
  81.     int    i, Child;    /* Children and the parent pointer */
  82.  
  83.     size = (obj[No].ob_spec.tedinfo->te_font == 3) ? 8 : 6;
  84.     te_x = (obj[No].ob_spec.tedinfo->te_just)
  85.             ? obj[No].ob_width - (obj[No].ob_spec.tedinfo->te_tmplen - 1) * size : 0;
  86.     if(obj[No].ob_spec.tedinfo->te_just == 2)
  87.             te_x /= 2;
  88.     te_x += obj[No].ob_x + size / 2;
  89.     Child = No;
  90.     for (i = No - 1; 0 <= i; i--)
  91.         if ((obj[i].ob_head <= Child) && (Child <= obj[i].ob_tail))    {
  92.             Child = i;
  93.             te_x += obj[i].ob_x;
  94.         }
  95.  
  96.     while ((te_x < mx) && (P_mask < obj[No].ob_spec.tedinfo->te_tmplen - 1)) {
  97.         if (obj[No].ob_spec.tedinfo->te_ptmplt[P_mask++] == '_')
  98.             P_text++;
  99.         te_x += size;
  100.     }
  101.     return P_text;
  102. }
  103.  
  104.  
  105. /*
  106.  *  Check to see if an object is hidden
  107.  *
  108.  *  tree = Address of dialog box to check
  109.  *  obj  = Object to check
  110.  *  flag = Flag to truly check for the object (usually TRUE)
  111.  *
  112.  *  Returns: TRUE = it is hidden
  113.  *             FALSE = it is not
  114.  */
  115. LOCAL int IsHidden(OBJECT *tree, int obj, int flag)
  116. {
  117.     int    index = obj, next;
  118.  
  119.     if (!(tree[obj].ob_flags & HIDETREE))
  120.         if (flag == TRUE || !(tree[obj].ob_state & DISABLED)) {
  121.             while ((next = tree[index].ob_next) != -1) {
  122.                 if ((tree[index].ob_flags & HIDETREE))
  123.                     return TRUE;
  124.                 index = next;
  125.             }
  126.             return FALSE;
  127.         }
  128.  
  129.     return TRUE;
  130. }
  131.  
  132.  
  133. /*
  134.  *  Check for a specified flag against an object
  135.  *
  136.  *  tree = Address of the dialog box
  137.  *  obj  = Object to check
  138.  *  flag = Boolean value to truly check or not (usually TRUE)
  139.  *  mask = Mask to check for; make sure it's an integer value!
  140.  *
  141.  *  Returns: TRUE = object is flag
  142.  *             FALSE = it is not
  143.  */
  144. LOCAL int IsFlag(OBJECT *tree, int obj, int flag, int mask)
  145. {
  146.     if ((flag & mask) && (!IsHidden(tree, obj, FALSE)))
  147.         return TRUE;
  148.  
  149.     return FALSE;
  150. }
  151.  
  152.  
  153. /*
  154.  *  Jump to the first editable object
  155.  *
  156.  *  tree = Address of the dialog box to go to the first object in
  157.  *
  158.  *  Returns: index of the first object
  159.  *             0 on failure
  160.  */
  161. LOCAL int FirstEdit(OBJECT *tree)
  162. {
  163.     int    index = 0;
  164.  
  165.     do {
  166.         index++;
  167.         if (IsFlag(tree, index, tree[index].ob_flags, EDITABLE))
  168.             return index;
  169.     }
  170.     while (!(tree[index].ob_flags & LASTOB));
  171.  
  172.     return 0;
  173. }
  174.  
  175.  
  176. /*
  177.  *  Jump to the last editable object
  178.  *
  179.  *  tree = Address of the dialog box to jump to the last object in
  180.  *
  181.  *  Returns: index of the last object
  182.  *             0 on failure
  183.  */
  184. LOCAL int LastEdit(OBJECT *tree)
  185. {
  186.     int    index = 0, last = 0;
  187.  
  188.     do {
  189.         index++;
  190.         if (IsFlag(tree, index, tree[index].ob_flags, EDITABLE))
  191.             last = index;
  192.     }
  193.     while (!(tree[index].ob_flags & LASTOB));
  194.  
  195.     if (last)
  196.         return last;
  197.  
  198.     return 0;
  199. }
  200.  
  201.  
  202. /*
  203.  *    Find next editable object
  204.  *
  205.  *    tree = Address of the dialog box to search
  206.  *    cobj = Current object the cursor is at
  207.  *
  208.  *    Returns: index of the next object
  209.  *             0 on failure
  210.  */
  211. LOCAL int NextEdit(OBJECT *tree, int cobj)
  212. {
  213.     int    index = cobj;
  214.     int    flag = FALSE;
  215.  
  216.     if (index) {
  217.         while (!(tree[index].ob_flags & LASTOB)) {
  218.             index++;
  219.             if (IsFlag(tree, index, tree[index].ob_flags, EDITABLE))
  220.                 return index;
  221.         }
  222.  
  223.         if (!flag)
  224.             return FirstEdit(tree);
  225.     }
  226.  
  227.     return 0;
  228. }
  229.  
  230.  
  231. /*
  232.  *    Clear all editable fields
  233.  *
  234.  *    tree = Object tree to clear out editable fields
  235.  */
  236. LOCAL int ClearAllEdit(OBJECT *tree)
  237. {
  238.     int    index = 0;
  239.  
  240.     do {
  241.         if (tree[++index].ob_flags & EDITABLE)
  242.             tree[index].ob_spec.tedinfo->te_ptext = "\0";
  243.     } while (!(tree[index].ob_flags & LASTOB));
  244.  
  245.     return FirstEdit(tree);
  246. }
  247.  
  248.  
  249. /*
  250.  *  Find the object before the current one
  251.  *
  252.  *  tree = Address of the dialog box to search
  253.  *  cobj = Current object that the cursor is at
  254.  *
  255.  *  Returns: the index of the previous editable object
  256.  *             0 on failure
  257.  */
  258. LOCAL int PrevEdit(OBJECT *tree, int cobj)
  259. {
  260.     int    index = cobj;
  261.     int    flag = FALSE;
  262.  
  263.     if (index) {
  264.         do {
  265.             index--;
  266.             if (IsFlag(tree, index, tree[index].ob_flags, EDITABLE))
  267.                 return index;
  268.         }
  269.         while (index);
  270.  
  271.         if (!flag)
  272.             return LastEdit(tree);
  273.     }
  274.  
  275.     return 0;
  276. }
  277.  
  278.  
  279. /*
  280.  *  Customized form_keybd call
  281.  *
  282.  *  win    = Window structure
  283.  *  key    = Keyboard keycode from EvntMulti
  284.  *    kstate = Keyboard status
  285.  *  nchr   = Processed keycode (0 if handled, otherwise, it
  286.  *           returns the keycode that was typed.)
  287.  *
  288.  *    Returns: 0 if an exitobject was selected
  289.  */
  290. GLOBAL int WForm_keybd(WINDOW *win, int key, int kstate, int *nobj, int *nchr)
  291. {
  292.     int n_key;
  293.  
  294.     n_key = nkc_tconv((key & 0xff) | (((long) key & 0xff00) << 8) | ((long) kstate << 24)) & ~(NKF_FUNC | NKF_RESVD | NKF_NUM);
  295.     *nchr = 0;
  296.  
  297.     if ((!win->edobject && n_key == NK_RET) || (n_key == (NK_RET | NKF_CTRL))) {
  298.         int    i = 0;
  299.         OBJECT *obj = win->tree;
  300.  
  301.         do {
  302.             if (obj->ob_flags & DEFAULT) {
  303.                 *nobj = i;
  304.                 return FALSE;
  305.             }
  306.             i++;
  307.         } while (!((obj++)->ob_flags & LASTOB));
  308.  
  309.         *nobj = 0;        
  310.         return TRUE;
  311.     }
  312.  
  313.     if (!win->edobject || n_key & NKF_ALT) {
  314.         int    i = 0, mask = (toupper(n_key & 0xff) & 0x7f) << 8;
  315.         OBJECT *obj = win->tree;
  316.  
  317.         do {
  318.             if (((obj->ob_type & 0x7f00) == mask) && !(obj->ob_state & DISABLED) && ((obj->ob_flags & SELECTABLE) || (obj->ob_flags & EXIT))) {
  319.                 *nobj = i;
  320.                 return FALSE;
  321.             }
  322.             i++;
  323.         }
  324.         while (!((obj++)->ob_flags & LASTOB));
  325.     }
  326.  
  327.     if (win->edobject) {
  328.         register char *text = win->tree[win->edobject].ob_spec.tedinfo->te_ptext;
  329.     
  330.         switch (n_key) {
  331.             case NK_ENTER:
  332.             case NK_DOWN:
  333.             case NK_TAB:
  334.             case NK_RET:
  335.                 edit_off(win);
  336.                 win->edobject = NextEdit(win->tree, win->edobject);
  337.                 win->edpos = (int) strlen(text);
  338.                 edit_on(win);
  339.                 break;
  340.  
  341.             case NK_UP:
  342.             case NK_TAB | NKF_LSH:
  343.             case NK_TAB | NKF_RSH:
  344.                 edit_off(win);
  345.                 win->edobject = PrevEdit(win->tree, win->edobject);
  346.                 win->edpos = (int) strlen(text);
  347.                 edit_on(win);
  348.                 break;
  349.  
  350.             case NK_UNDO:
  351.                 WCallUndoDispatcher(win);
  352.                 break;
  353.  
  354.             case NK_HELP:
  355.                 WCallHelpDispatcher(win);
  356.                  break;
  357.  
  358.             case NK_F1:
  359.                 WCallFKeyDispatcher(win, 1);
  360.                 break;
  361.  
  362.             case NK_F2:
  363.                 WCallFKeyDispatcher(win, 2);
  364.                 break;
  365.  
  366.             case NK_F3:
  367.                 WCallFKeyDispatcher(win, 3);
  368.                 break;
  369.  
  370.             case NK_F4:
  371.                 WCallFKeyDispatcher(win, 4);
  372.                 break;
  373.  
  374.             case NK_F5:
  375.                 WCallFKeyDispatcher(win, 5);
  376.                 break;
  377.  
  378.             case NK_F6:
  379.                 WCallFKeyDispatcher(win, 6);
  380.                 break;
  381.  
  382.             case NK_F7:
  383.                 WCallFKeyDispatcher(win, 7);
  384.                 break;
  385.  
  386.             case NK_F8:
  387.                 WCallFKeyDispatcher(win, 8);
  388.                 break;
  389.  
  390.             case NK_F9:
  391.                 WCallFKeyDispatcher(win, 9);
  392.                 break;
  393.  
  394.             case NK_F10:
  395.                 WCallFKeyDispatcher(win, 10);
  396.                 break;
  397.  
  398.             case NK_CLRHOME | NKF_CTRL:
  399.                 {
  400.                     int x, y, w, h;
  401.  
  402.                     win->edobject = ClearAllEdit(win->tree);
  403.                     WWindGet(win, WF_WORKXYWH, &x, &y, &w, &h);
  404.                     WRedrawWindow(win, x, y, w, h);
  405.                 }
  406.                 break;
  407.  
  408.             case NK_LEFT | NKF_LSH:
  409.             case NK_LEFT | NKF_RSH:
  410.                 edit_pos(win, 0);
  411.                 break;
  412.  
  413.             case NK_RIGHT | NKF_LSH:
  414.             case NK_RIGHT | NKF_RSH:
  415.                 edit_pos(win, (int) strlen(text));
  416.                 break;
  417.  
  418.             case NK_RIGHT | NKF_CTRL:
  419.                 {
  420.                     char *ptr = text + win->edpos;
  421.  
  422.                     if (*ptr) {
  423.                         while (*(++ptr))
  424.                             if (isalnum(*ptr) && !isalnum(*(ptr - 1)))
  425.                                 break;
  426.  
  427.                         edit_pos(win, (int) (ptr - text));
  428.                     }
  429.                 }
  430.                 break;
  431.  
  432.             case NK_LEFT | NKF_CTRL:
  433.                 if (win->edpos) {
  434.                     char *ptr = text + win->edpos;
  435.  
  436.                     while (text != --ptr)
  437.                         if (!isalnum(*ptr) && text != ptr - 1)
  438.                             if (isalnum(*(ptr - 1)))
  439.                                 break;
  440.  
  441.                     edit_pos(win, (int) (ptr - text));
  442.                 }
  443.                 break;
  444.  
  445.             case NK_LEFT:
  446.                 {
  447.                     int pos = win->edpos;
  448.  
  449.                     pos--;
  450.                     if (pos<0) pos = 0;
  451.                     edit_pos(win, pos);
  452.                 }
  453.                 break;
  454.  
  455.             case NK_RIGHT:
  456.                 {
  457.                     int pos = win->edpos;
  458.  
  459.                     pos++;
  460.                     if (pos>(int) strlen(text)) pos = (int) strlen(text);
  461.                     edit_pos(win, pos);
  462.                 }
  463.                 break;
  464.  
  465.             case NK_UP | NKF_LSH:
  466.             case NK_UP | NKF_RSH:
  467.             case NK_CLRHOME:
  468.                 {
  469.                     int prev = win->edobject;
  470.                     int storage;
  471.  
  472.                     storage = FirstEdit(win->tree);
  473.                     if (storage == prev) {
  474.                         win->edobject = prev;
  475.                         edit_pos(win, 0);
  476.                     } else {
  477.                         edit_off(win);
  478.                         win->edobject = storage;
  479.                         edit_on(win);
  480.                     }
  481.                 }
  482.                 break;
  483.  
  484.             case NK_CLRHOME | NKF_LSH:
  485.             case NK_CLRHOME | NKF_RSH:
  486.             case NK_DOWN | NKF_LSH:
  487.             case NK_DOWN | NKF_RSH:
  488.                 {
  489.                     int prev = win->edobject;
  490.                     int    storage;
  491.  
  492.                     storage = LastEdit(win->tree);
  493.                     if (storage == prev) {
  494.                         win->edobject = prev;
  495.                         edit_pos(win, 0);
  496.                     } else {
  497.                         edit_off(win);
  498.                         win->edobject = storage;
  499.                         edit_on(win);
  500.                     }
  501.                 }
  502.                 break;
  503.  
  504.             case NK_INS:
  505.                 WGrafMouse(ARROW);
  506.                 {
  507.                     int edittype = WFind_EditType(win);
  508.                     *nchr = (char) WAscii_Table(edittype);
  509.                 }
  510.                 break;
  511.  
  512.             default:
  513.                 *nchr = key;
  514.                 break;
  515.         }
  516.     }
  517.  
  518.     *nobj = win->edobject;
  519.  
  520.     return TRUE;
  521. }
  522.  
  523. GLOBAL int WFind_EditType(WINDOW *win)
  524. {
  525.     int type, pos = 0, len = strlen(win->tree[win->edobject].ob_spec.tedinfo->te_pvalid);
  526.  
  527.     do {
  528.         pos++;
  529.  
  530.         switch(win->tree[win->edobject].ob_spec.tedinfo->te_pvalid[pos]) {
  531.             case '9': return E_NUMERIC;
  532.             case 'a': return E_LOW_ASCII;
  533.             case 'n': return E_LOW_NUMERIC;
  534.             case 'p': return E_LOW_PATH;
  535.             case 'A': return E_UP_ASCII;
  536.             case 'N': return E_UP_NUMERIC;
  537.             case 'P': return E_UP_PATH;
  538.             case 'X': return E_ANY;
  539.             case 'S': return E_SPECIAL;
  540.         }
  541.     } while (pos < len);
  542.  
  543.     return 0;
  544. }
  545.